package edu.luc.concordia;

import java.io.*;
import java.util.*;

import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.*;
import javax.xml.transform.stream.*;

import org.w3c.dom.*;

/**
 * Copyright 2008 Project Concordia
 * <p>
 * This file is part of RetailReturnSystem.
 * <p>
 * RetailReturnSystem is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * <p>
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * <p>
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <a href="http://www.gnu.org/licenses/">http://www.gnu.org/licenses/</a>.
 * <hr>
 * Calculates the final pieces, generate the receipt, and updates the receipt file.
 * @author Blanche Faur
 * @version 0.1 2008-10-06
 */

public class ReceiptGenerator {

	private ArrayList<Product> myScannedItems = new ArrayList();
	private ArrayList<String> myFinalReceipt = new ArrayList();


	/**
	 * Constructor class
	 * @param items - is the list of scanned items generated by PurchaseRecorder class.
	 */
	public ReceiptGenerator(ArrayList<Product> items){
		myScannedItems = items;
	}

	/**
	 * Calculate the final prices with Subtotal, 
	 * GST (Goods and Services Tax) and Total
	 */
	private void calculateFinalPrices(){

		double subTotal = 0.0;
		
		//printing the lines with items
		for (int i = 0; i < myScannedItems.size(); i++){

			Product tempProduct = myScannedItems.get(i);
			String description = tempProduct.getDescription();
			String uid = tempProduct.getUID();
			ArrayList<PriceScheme> priceScheme = tempProduct.getPriceScheme();
			double price = priceScheme.get(0).getPrice();
			myFinalReceipt.add(uid + " " + description + " " + price);

			subTotal += price;

		}

		double tax = 0.0;
		
		//to display the footer of the receipt 
		tax = subTotal * 0.07f;
		myFinalReceipt.add("SubTotal = $" + subTotal);
		myFinalReceipt.add("GST = $" + tax);
		myFinalReceipt.add("Total: $" + (subTotal + tax));

	}


	/**
	 * To open the file "output" and add data into it.
	 */

	private void updateReceiptFile(){

		FileWriter writer = null;
		double subTotal = 0.0;
		double tax = 0.0;
		double total = 0.0;
		
		//Creating an empty XML Document
			DocumentBuilderFactory dbfac =  DocumentBuilderFactory.newInstance();
			DocumentBuilder docBuilder = null;
			try {
				docBuilder = dbfac.newDocumentBuilder();
				
			} catch (ParserConfigurationException e) {
				e.printStackTrace();
			}
			Document doc = docBuilder.newDocument();

			//Creating the XML tree

			//create the root element and add it to the document
			Element root = doc.createElement("finalReceipt");
			doc.appendChild(root);

			for (int i = 0; i < myScannedItems.size(); i++){

				Product tempProduct = myScannedItems.get(i);

				//UID
				String uid = tempProduct.getUID();
				//create child element and add to root
				Element child1 = doc.createElement("uid");
				root.appendChild(child1);
				//to get uid and add uid text element to the child
				Text text1 = doc.createTextNode(uid);
				child1.appendChild(text1);

				//Description
				String description = tempProduct.getDescription();
				//create child element and add to root
				Element child2 = doc.createElement("description");
				root.appendChild(child2);
				//to get description and add description text element to the child
				Text text2 = doc.createTextNode(description);
				child2.appendChild(text2);
				
				//SubTotal
				ArrayList<PriceScheme> priceScheme = tempProduct.getPriceScheme();
				double price = priceScheme.get(0).getPrice();
				subTotal += price;
				String totalPriceString = Double.toString(subTotal);
				//create child element and add to root
				Element child4 = doc.createElement("subTotal");
				root.appendChild(child4);
				//to get subTotal and add subTotal text element to the child
				Text text4 = doc.createTextNode(totalPriceString);
				child4.appendChild(text4);


				//GST
				tax = subTotal * 0.07f;
				String taxString = Double.toString(tax);
				//create child element and add to root
				Element child5 = doc.createElement("gstTax");
				root.appendChild(child5);
				//to get tax and add tax text element to the child
				Text text5 = doc.createTextNode(taxString);
				child5.appendChild(text5);
				
				//Total
				total = subTotal + tax;
				String totalString = Double.toString(total);
				//create child element and add to root
				Element child6 = doc.createElement("total");
				root.appendChild(child6);
				//to get tax and add tax text element to the child
				Text text6 = doc.createTextNode(totalString);
				child6.appendChild(text6);

				//Output the XML
				//set up a transformer
				TransformerFactory transfac = TransformerFactory.newInstance();
				Transformer trans = null;
				try {
					trans = transfac.newTransformer();
					
				} catch (TransformerConfigurationException e) {
					e.printStackTrace();
				}
				trans.setOutputProperty(OutputKeys.INDENT, "yes");

				//create string from xml tree
				StringWriter sw = new StringWriter();
				StreamResult result = new StreamResult(sw);
				DOMSource source = new DOMSource(doc);
				try {
					trans.transform(source, result);
					
				} catch (TransformerException e) {
					e.printStackTrace();
				}
				String xmlString = sw.toString();
				
				//to display xml in myReceipt.xml and close it
				try 
				{		
					writer = new FileWriter("C://myReceipt.xml", true);
					writer.write(xmlString);
					writer.flush();
					writer.close();					
				} 
				catch (IOException e) 
				{
					e.printStackTrace();
				}				

			}
	}


	/**
	 * Generates the final receipt.
	 * @return generateFinalReceipt - an ArrayList of myFinalReceipt called by the 
	 * CalculateFinalPrices() and UpdateReceiptFile() methods
	 */
	public ArrayList<String> generateFinalReceipt(){
		calculateFinalPrices();
		updateReceiptFile();
		return myFinalReceipt;

	}

}